home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-06 | 13.7 KB | 212 lines | [TEXT/MMCC] |
- //------------------------------------------------------------------------------
- // File: view.cp
- // Date: 9/18/94
- // Author: Bretton Wade
- //
- // Description: this file contains the class methods for a view of space
- //
- //------------------------------------------------------------------------------
-
- #include "view.h"
- #include "arcball.h"
- #include "colors.h"
- #include "bsptree_3d.h"
-
- //------------------------------------------------------------------------------
- // static variables
- //------------------------------------------------------------------------------
- view *view::current = 0; // part of the current drawing environment
-
- //------------------------------------------------------------------------------
- // constructor
- //------------------------------------------------------------------------------
- view::view (window *w) : gworld (w), // view constructor
- transformation (matrix_3d::identity), // matrix_3d constructor
- inverse (matrix_3d::identity), // matrix_3d constructor
- cam (point_3d (R(0.0), R(0.0), R(5.0)), ORIGIN_3D, LensToFOV (50)) // camera_3d constructor
- { // begin
- gui = new arcball (ORIGIN_2D, R(0.95)); // make the arcball interface
- eye = cam.Eye (); // assign the untransformed eye point_3d
- } // end
-
- //------------------------------------------------------------------------------
- // destructor
- //------------------------------------------------------------------------------
- view::~view (void) // destructor
- { // begin
- delete gui; // clean up the interface object
- } // end
-
- //------------------------------------------------------------------------------
- // Move the pen to a point
- //------------------------------------------------------------------------------
- void view::MoveToPt (const point_2d &vp) const // move to a point_2d
- { // begin
- Point p = vdctodc (vp); // figure out the screen point that corresponds to the desired point
- MoveTo (p.h, p.v); // move the pen there
- } // end
-
- //------------------------------------------------------------------------------
- // Draw a line to a point
- //------------------------------------------------------------------------------
- void view::LineToPt (const point_2d &vp) const // draw a line to a point_2d
- { // begin
- Point p = vdctodc (vp); // figure out the screen point that corresponds to the desired point
- LineTo (p.h, p.v); // draw a line there
- } // end
-
- //------------------------------------------------------------------------------
- // Draw a circle
- //------------------------------------------------------------------------------
- void view::Circle (const point_2d &a, const point_2d &b) const // draw a circle defined by the rectangle 'ab'
- { // begin
- Point p1 = vdctodc (a), // figure out the screen location
- p2 = vdctodc (b); // figure out the screen location
- Rect r; // a rectangle
- SetRect (&r, p1.h, p2.v, p2.h + 1, p1.v + 1); // set up the rectangle for the oval
- EraseOval (&r); // fill the oval with the background color
- FrameOval (&r); // draw the oval outline
- } // end
-
- //------------------------------------------------------------------------------
- // Draw the cursor crosshair
- //------------------------------------------------------------------------------
- void view::CrossHair (const point_2d &vp) const // draw a crosshair at the specified location
- { // begin
- Point p = vdctodc (vp); // figure out the screen location
- MoveTo (p.h - 5, p.v); // move to the left
- LineTo (p.h + 5, p.v); // line to the right
- MoveTo (p.h, p.v - 5); // move to the top
- LineTo (p.h, p.v + 6); // line to the bottom
- } // end
-
- //------------------------------------------------------------------------------
- // Draw a polygon
- //------------------------------------------------------------------------------
- void view::DrawPolygon (polyptr poly) // draw a polygon (transformed by the camera_3d)
- { // begin
- if ((eye | poly->Plane ()) > R(0.0)) // if the polygon is not a backface
- { // begin
- static vector_3d light = vector_3d (4, 8, 6).Normalize (); // lighting vector
- real shade = (poly->Plane () | light) * 0.8 + 0.2; // compute the lighting on this polygon
- if (shade < 0.2) shade = 0.2; // clamp it to the ambient factor
- if (shade > 1.0) shade = 1.0; // and no brighter than white
- RGBColor color; // the screen color
- color.red = color.blue = color.green = 65535.0 * shade; // set the screen color to be the right shade of grey
- RGBBackColor (&color); // set the background color
- PolyHandle polyh = OpenPoly (); // get ready to draw the polygon
- point_3d pt = poly->Vertex (poly->Count () - 1) * viewing; // compute the screen location of the last point
- MoveToPt (point_2d (pt[X], pt[Y])); // move there
- for (short i = 0; i < poly->Count (); i++) // for all points
- { // begin
- pt = poly->Vertex (i) * viewing; // compute the screen location
- LineToPt (point_2d (pt[X], pt[Y])); // line to there
- } // end
- ClosePoly (); // finished drawing the polygon
- ErasePoly (polyh); // fill it with the computed shade
- FramePoly (polyh); // draw an outline
- KillPoly (polyh); // release the memory
- RGBBackColor (&WHITE); // reset the background color to be friendly
- } // end
- } // end
-
- //------------------------------------------------------------------------------
- // Draw the whole scene
- //------------------------------------------------------------------------------
- void view::DrawScene (void) // draw the scene that this view is for
- { // begin
- viewing = transformation * cam.Transform (); // compute the viewing transformation
- eye = cam.Eye () * inverse; // and the eye location
- gui->DrawBackground (); // draw the interface background, so it's always there
- extern bsptree *world; // the world is not defined here...
- world->Draw (eye); // draw the scene
- } // end
-
- //------------------------------------------------------------------------------
- // Handle a mouse down event in the user area
- //------------------------------------------------------------------------------
- void view::HandleClick (EventRecord &event) // handle mouse down/up
- { // begin
- HideCursor (); // prevent flicker of the mouse cursor
- sum = transformation; // copy the transformation
- gui->Click (dctovdc (event.where)); // tell the interface object about the click
- Point last_pt; // place store the current location of the mouse
- do // loop
- { // begin
- GetMouse (&event.where); // check the current mouse location
- if (*(long *) &(event.where) != *(long *) &(last_pt)) // if the mouse has moved
- { // begin
- transformation = sum * gui->Drag (dctovdc (event.where)); // set up the current transformation
- inverse = transformation.Inverse (); // compute its inverse
- StartDrawing (); // prepare the offscreen drawing world
- //gui->DrawBackground (); // draw the interface background
- DrawScene (); // draw the scene
- gui->DrawForeground (); // draw the interface foreground
- StopDrawing (); // clean up the offscreen drawing world and update the screen
- } // end
- last_pt = event.where; // copy the current mouse location
- } // end
- while (StillDown ()); // loop until the user releases the mouse button
- StartDrawing (); // prepare the offscreen drawing world
- DrawScene (); // draw the image
- StopDrawing (); // clean up the offscreen drawing world and update the screen
- ShowCursor (); // give the user back the cursor
- } // end
-
- //------------------------------------------------------------------------------
- // Change the size of the user area
- //------------------------------------------------------------------------------
- void view::Resize (EventRecord &event) // recompute sizing information from parent
- { // begin
- gworld::Resize (event); // default behavior
- Rect rect = (*region)->rgnBBox; // temporary to simplify code
- real width = rect.right - rect.left, // compute the width of the window
- height = rect.bottom - rect.top; // compute the hight of the window
- ysize = height / R(2.0); // compute the y halfsize
- xsize = width / R(2.0); // compute the x halfsize
- aspect = (width > height) ? ysize : xsize; // set the aspect to be the smaller of the two
- StartDrawing (); // set up the drawing environment
- DrawScene (); // redraw the image
- StopDrawing (DONT_UPDATE); // reset the drawing environment
- } // end
-
- //------------------------------------------------------------------------------
- // convert a screen location to the range (-1..1, -1..1)
- //------------------------------------------------------------------------------
- point_2d view::dctovdc (const Point &p) const // map screen coordinates to virtual device coordinates
- { // begin
- short x = p.h - (*region)->rgnBBox.left, // adjust the location to the edge of the view
- y = p.v - (*region)->rgnBBox.top; // adjust the location to the edge of the view
- return point_2d ((x - xsize) / aspect, (y - ysize) / -aspect); // return the converted point_3d
- } // end
-
- //------------------------------------------------------------------------------
- // convert a point in the range (-1..1, -1..1) to a screen coordinate
- //------------------------------------------------------------------------------
- Point view::vdctodc (const point_2d &p) const // map virtual device coordinates to screen coordinates
- { // begin
- Point pt; // storage for the return value
- pt.h = (short) ((p[X] * aspect) + xsize); // convert the x coordinate to screen coordinates
- pt.v = (short) ((p[Y] * -aspect) + ysize); // convert the y coordinate to screen coordinates
- return pt; // return the converted point_3d
- } // end
-
- //------------------------------------------------------------------------------
- // start drawing to the gworld
- //------------------------------------------------------------------------------
- void view::StartDrawing (gw_erase e) // lock down the gworld and set the port appropriately
- { // begin
- current = this; // set the current drawing world
- gworld::StartDrawing (e); // do the parental thing
- } // end
-
- //------------------------------------------------------------------------------
- // stop drawing to the gworld
- //------------------------------------------------------------------------------
- void view::StopDrawing (gw_update u) // unlock the gworld and reset the port
- { // begin
- current = 0; // make sure the current drawing world is empty
- gworld::StopDrawing (u); // do the parental thing
- } // end
-
- //------------------------------------------------------------------------------